﻿#pragma once
#include <opencv2/dnn/dnn.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

#include <chrono>
#include <cmath>
#include <exception>
#include <fstream>
#include <iostream>
#include <limits>
#include <numeric>
#include <string>
#include <queue>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#else
#include <dlfcn.h>
#endif

#include "base_util/utils.h"
#include "model_error_code.h"

namespace ai {
typedef int (*INIT_PARAM)(LogInfo*, std::string);
typedef int (*GET_ALL_MODEL_INFO)(std::vector<au::authModelLabel>&);
typedef int (*GET_MODEL)(std::string, void**, void*, void** ,int);

#define MAX_SUPPORT_CHANNEL 4

class BasePredictor;
class ModelManager
{
public:
  ModelManager(LogInfo *log_info);
  virtual ~ModelManager();
  
  int init_model(std::vector<InitModelData> &init_model_datas, int debug_mode);
  virtual int init_model_imp(std::string model_path, std::string cfg_path, int gpu_idx, ai::InitModelData &imd, BasePredictor** infer, int debug_mode) = 0;

  virtual int free_model(int md_idx) = 0;
  // 线程执行
  int stop_run_thread();
  int start_run_thread();
  int set_data(std::string model_id, int& idx, stream::ImageBlob& img);
  int set_data(std::vector<std::string> model_ids, std::vector<int>& idxs, stream::ImageBlob& img);
  int get_data(std::string model_id, int idx, ai::InferResult& infer_res);
  int get_data(std::vector<std::string> model_ids, std::vector<int> idxs, ai::InferResult& infer_res);

public:
  LogInfo *log_ifo;
  void *auth_handle = nullptr;
  INIT_PARAM init_param = nullptr;
  GET_ALL_MODEL_INFO get_all_model_info = nullptr;
  GET_MODEL get_model = nullptr;


  // int predictor_size_;

  std::map<std::string, ModuleInfo> total_mdl;
  std::vector<BasePredictor*> infers;
  int init_ok;
  std::map<std::string, std::vector<stream::ImageBlob*>> in_datas;
	std::mutex in_data_mtx;
  // 维护 in_datas 的全局索引
  std::map<std::string, int> in_loop_idx;
  int set_data_idx = 0;
	std::mutex out_data_mtx;
  std::map<std::string, std::map<int, ai::InferResult>> out_datas;


private:
  std::atomic_int stop_flag1;
  std::atomic_int stop_flag2;
	std::mutex run_mtx2;
  uint8_t in_data_cnt;

};


}